﻿using System;
using System.Windows.Forms;
using BReusable;


public static class ControlExtensions
	{

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="dateTimePicker"></param>
		/// <param name="dataSource"></param>
		/// <param name="valueMember"></param>
		/// <param name="showCheckBox"></param>
		/// <remarks>With help from Dan Hanan at http://blogs.interknowlogy.com/danhanan/archive/2007/01/21/10847.aspx</remarks>
		public static void BindNullableValue(this DateTimePicker dateTimePicker, BindingSource dataSource, String valueMember,
			bool showCheckBox)
		{
			var binding = new Binding("Value", dataSource, valueMember, true);

			//OBJECT PROPERTY --> CONTROL VALUE
			binding.Format += ((sender, e) =>
			                   	{
			                   		Binding b = sender as Binding;
				
			                   		if (b != null)
			                   		{
			                   			DateTimePicker dtp = (binding.Control as DateTimePicker);
			                   			if (dtp != null)
			                   			{
			                   				if (e.Value == null)
			                   				{

			                   					dtp.ShowCheckBox = showCheckBox;
			                   					dtp.Checked = false;

			                   					// have to set e.Value to SOMETHING, since it's coming in as NULL
			                   					// if i set to DateTime.Today, and that's DIFFERENT than the control's current
			                   					// value, then it triggers a CHANGE to the value, which CHECKS the box (not ok)
			                   					// the trick - set e.Value to whatever value the control currently has. 
			                   					// This does NOT cause a CHANGE, and the checkbox stays OFF.

			                   					e.Value = dtp.Value;

			                   				}
			                   				else
			                   				{
			                   					dtp.ShowCheckBox = showCheckBox;
			                   					dtp.Checked = true;
			                   					// leave e.Value unchanged - it's not null, so the DTP is fine with it.
			                   				}

			                   			}

			                   		}
			                   	});
			// CONTROL VALUE --> OBJECT PROPERTY
			binding.Parse += ((sender, e) =>
			                  	{
			                  		// e.value is the formatted value coming from the control. 
			                  		// we change it to be the value we want to stuff in the object.
			                  		var b = sender as Binding;

			                  		if (b != null)
			                  		{
			                  			var dtp = (b.Control as DateTimePicker);
			                  			if (dtp != null)
			                  			{
			                  				if (dtp.Checked == false)
			                  				{
			                  					dtp.ShowCheckBox = showCheckBox;
			                  					dtp.Checked = false;
												//used to cast null to dateTime?
			                  					e.Value = null;
			                  				}
			                  				else
			                  				{
			                  					DateTime val = Convert.ToDateTime(e.Value);
			                  					e.Value = val;
			                  				}
			                  			}
			                  		}
			                  	});
			dateTimePicker.DataBindings.Add(binding);

		}

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="comboBox"></param>
		/// <param name="dataSource"></param>
		/// <param name="valueMember"></param>
		/// <remarks>With help from Dan Hanan at http://blogs.interknowlogy.com/danhanan/archive/2007/01/21/10847.aspx</remarks>
		public static void BindNullableSelectedValue(this ComboBox comboBox, BindingSource dataSource, String valueMember)
		{
			var binding = new Binding(Member.Name<ComboBox>(item=>item.SelectedValue), dataSource, valueMember, true);

			//OBJECT PROPERTY --> CONTROL VALUE
			binding.Format += ((sender, e) =>
			{
				Binding b = sender as Binding;

				if (b != null)
				{
					var  cBox = (binding.Control as ComboBox);
					if (cBox != null)
					{
						if (e.Value == null)
						{

							cBox.SelectedItem=null;

						}
						//else
						//{
							//dtp.ShowCheckBox = showCheckBox;
							//dtp.Checked = true;
							// leave e.Value unchanged - it's not null, so the DTP is fine with it.
						//}

					}

				}
			});
			// CONTROL VALUE --> OBJECT PROPERTY
			binding.Parse += ((sender, e) =>
			{
				// e.value is the formatted value coming from the control. 
				// we change it to be the value we want to stuff in the object.
				var b = sender as Binding;

				if (b != null)
				{
					var cBox = (b.Control as ComboBox);
					if (cBox != null)
					{
						e.Value = cBox.SelectedItem != null ? cBox.SelectedValue : null;
					}
				}
			});
			comboBox.DataBindings.Add(binding);

		}
		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="control"></param>
		/// <param name="a"></param>
		public static void InvokeSafe(this Control control, Action a)
		{
			if (control.InvokeRequired)
				control.Invoke(a);
			else
				a();
		}

		/// <summary>
		/// From BReusable
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="control"></param>
		/// <param name="doWhat"></param>
		public static void InvokeSafe<T>(this T control, Action<T> doWhat) where T : Control
		{
			Action a = () => doWhat(control);
			control.InvokeSafe(a);
		}
		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="control"></param>
		/// <param name="text"></param>
		public static void InvokeSafeText(this Control control, String text)
		{
			Action a = () => control.Text = text;
			control.InvokeSafe(a);
		}
		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="control"></param>
		/// <param name="enabled"></param>
		public static void InvokeSafeEnabled(this Control control, bool enabled)
		{
			Action a = () => control.Enabled = enabled;
			control.InvokeSafe(a);
		}
		/// <summary>
		/// From BReusable
		/// </summary>
		/// <param name="control"></param>
		/// <param name="text"></param>
		public static void InvokeSafeTextAdd(this Control control, string text)
		{
			control.InvokeSafe(() => control.Text += text);
		}

	
		public static void AddEnum<TEnum>(this ComboBox comboBox) where TEnum:struct
		{
			foreach (var item in Enum.GetValues(typeof(TEnum)))
			{
				comboBox.Items.Add(item.DirectCast<TEnum>());
			}
		}

	}

